package cloud.consumer.feign.controller;

import com.xfanonymous.cloud.api.PayFeignApi;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @auther xfanonymous
 * @create 2023-12-26 22:37
 *
 * Resilience4J CircuitBreaker 断路器功能验证
 * 1. 客户端通过FeignAPI调用服务端
 * 2. @CircuitBreaker(name="service-name", fallbackMethod="method-name")
 *      service-name 和yml配置中指定的服务名一致
 *      fallbackMethod 指定服务降级的兜底方法
 * 3. 访问客户端 GET http://localhost:82/feign/pay/circuit/{{id}}
 *    客户端配置了Resilience4J CircuitBreaker和兜底方法
 *    Handler通过Feign调用到服务端 GET http://localhost:8001/pay/circuit/{{id}}
 *    当服务端抛出异常时，客户端触发兜底方法
 * 4. 当多次请求异常，触达异常次数百分比后，服务熔断，正常请求也会阻塞
 * 5. 一段时间后，服务自动处于半开状态，多次请求正常后，熔断器转为关闭，服务转为正常
 *
 *
 * Resilience BulkHead 舱壁隔离
 * 1. @BulkHead(name="service-name",fallbackMethod="method-name",type="bulkhead-type")
 *
 *
 * Resilience4J RateLimit
 * 1. @RateLimiter(name = "cloud-payment-service", fallbackMethod = "myRateLimitFallback")
 */
@RestController
public class OrderCircuitController
{
    @Resource
    private PayFeignApi payFeignApi;

    /**
     * Resilience4J CircuitBreaker 断路器功能验证
     */
    @GetMapping(value = "/feign/pay/circuit/{id}")
    @CircuitBreaker(name = "cloud-payment-service", fallbackMethod = "myCircuitFallback")
    public String myCircuitBreaker(@PathVariable("id") Integer id)
    {
        return payFeignApi.myCircuit(id);
    }

    // 服务降级后的兜底处理方法
    public String myCircuitFallback(Integer id,Throwable t) {
        // 容错处理逻辑，返回备用结果
        return "myCircuitFallback，系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~";
    }


    /**
     * Resilience4J Semaphore BulkHead 舱壁隔离
     */
    @GetMapping(value = "/feign/pay/bulkhead/{id}")
    @Bulkhead(name = "cloud-payment-service",
              fallbackMethod = "myBulkheadFallback", type = Bulkhead.Type.SEMAPHORE)
    public String myBulkhead(@PathVariable("id") Integer id) {
        return payFeignApi.myBulkhead(id);
    }

    public String myBulkheadFallback(Throwable t) {
        return "myBulkheadFallback，隔板超出最大数量限制，系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~";
    }


    /**
     * Resilience4J FixedThreadPool Bulkhead 舱壁隔离
     */
    @GetMapping(value = "/feign/pay/bulkhead/pool/{id}")
    @Bulkhead(name = "cloud-payment-service",
            fallbackMethod = "myBulkheadPoolFallback", type = Bulkhead.Type.THREADPOOL)
    public CompletableFuture<String> myBulkheadTHREADPOOL(@PathVariable("id") Integer id)
    {
        System.out.println(Thread.currentThread().getName()+"\t"+"---开始进入");
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"\t"+"---准备离开");

        return CompletableFuture.supplyAsync(() ->
                payFeignApi.myBulkhead(id)+"\t"+"Bulkhead.Type.THREADPOOL");
    }

    public CompletableFuture<String> myBulkheadPoolFallback(Integer id, Throwable t)
    {
        return CompletableFuture.supplyAsync(() ->
                "Bulkhead.Type.THREADPOOL,系统繁忙，请稍后再试-----/(ㄒoㄒ)/~~");
    }


    /**
     * Resilience4J RateLimit
     */
    @GetMapping(value = "/feign/pay/ratelimit/{id}")
    @RateLimiter(name = "cloud-payment-service", fallbackMethod = "myRatelimitFallback")
    public String myRateLimit(@PathVariable("id") Integer id)
    {
        return payFeignApi.myRateLimit(id);
    }

    public String myRateLimitFallback(Integer id, Throwable t)
    {
        return "你被限流了，禁止访问/(ㄒoㄒ)/~~";
    }
}